package fr.insalyon.sims.broadcast.network;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;

/**
 * This class is a stream receiver for TCP protocol.
 * 
 * @author GONZALEZ Silvia, GOTTERO Jeremie, SATTAYAKAWEE Nutchanat
 *
 */
public class TCPStreamReceiver extends BaseStreamReceiver {
	// ------------------------------------------------------- CONSTANTS -- //
	// ------------------------------------------------------ ATTRIBUTES -- //
	/**
	 * listening port of the receiver
	 */
	private int port;
	/**
	 * socket of receiver
	 */
	private Socket socket;
	/**
	 * input stream to receiver data
	 */
	private BufferedInputStream input;
	
	// ---------------------------------------------------- CONSTRUCTORS -- //
	/**
	 * Constructor
	 * 
	 * @param port listening port number of the receiver 
	 */
	public TCPStreamReceiver(int port) {
		this.port = port;
	}
	
	// --------------------------------------------------------- METHODS -- //

	public void connect() {
		// No connection yet
	}
	
	public void disconnect() {
		// Disconnection job done in clean up
	}
	
	// ------------------------------------------------- PRIVATE METHODS -- //
	/**
	 * Initialise the receiver (socket and input stream)
	 */
	protected void init() throws IOException {
		// Wait a TCP/IP client connection
		ServerSocket serverSocket = new ServerSocket(port);
		this.socket = serverSocket.accept();
		
		// Set a 1s timeout on socket
		this.socket.setSoTimeout(1000);
		
		this.input = new BufferedInputStream(socket.getInputStream());
	}

	/**
	 * Reads the stream and sends the data to the its listeners. Maximum data for each reading is 2 KB.
	 */
	protected void readStream() throws IOException {
		// Read 2kB on socket
		byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
		
		try {
			int length = input.read(buffer, 0, buffer.length);
			if (length != -1)
				fireDataReceived(buffer, 0, length);
		} catch (SocketTimeoutException e) {
			// Ignored
		}
	}
	
	/**
	 * Closes the socket and input stream.
	 */
	protected void cleanUp() {
		try {
			// Release socket resources
			this.input.close();
			this.socket.close();
		} catch (IOException e) {
			// Ignoré
		}
	}
	
	// --------------------------------------------------- INNER CLASSES -- //
}
